﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.WindowsAPICodePack.Taskbar;
using Microsoft.WindowsAPICodePack.Shell;
using System.Diagnostics;
using System.Security;
using System.Media;
using System.Reflection;
using System.Drawing;

namespace GoogleAppsTools
{
    public partial class GoogleManager : Form
    {
        #region Declarations
        //Other forms
        private NewEvent newEventForm = new NewEvent(); //the window to create a new event in the calendar
        private SettingsForm applicationSettingsForm = new SettingsForm(); //the window to change the application settings

        //Lists for new mail/events and old mail/events to check against
        private List<NewMail> newEmails; //contains the new unread emails
        private List<NewMail> oldEmails = new List<NewMail>(); //contains the previously unread emails
        private List<NewMail> oldEmailsForBitmaps = new List<NewMail>(); //contains the previously unread emails, used for creating bitmaps and needs to be different from above
        private List<CalendarInfo> AllCalendars = new List<CalendarInfo>(); //list containing all the calendar events for today
        private List<CalendarInfo> oldAllCalendarsForBitmaps = new List<CalendarInfo>();

        private SoundPlayer newMailSound = new SoundPlayer(@"c:\Windows\Media\chimes.wav"); //sound to play if there is new mail

        //Windows 7 API
        private TaskbarManager windowsTaskbar = TaskbarManager.Instance; //the taskbarManager object, that manages windows 7 icons, jumplists and thumbnails
        private Microsoft.WindowsAPICodePack.Taskbar.JumpList myJumpList; //the jumplist object, used to add items to the application jump list in the taskbar
        private TabbedThumbnail newThumbnail; //the thumbnail object for the taskbar.  Only 1 object is created, and it's bitmap is changed if the next/previous buttons are clicked.  Doing it this way stops the thumbnail buttons dissappearing when the next/previous buttons are clicked.

        //Misc. declarations for internal functions
        private int numberOfNewEvents = 0; //holds the number of new events
        private int emailNumber = 0; //keeps track of the position in the list of bitmaps. Starts at zero and returns to zero if there are any changes
        private Control myControl = new Control(); //Associates the thumbnail buttons with the thumbnail image in the taskbar and stops the bitmap appearing in the applciation window.
        private List<Bitmap> allBitmaps = new List<Bitmap>(); //create list to hold all the bitmap images
        private bool errorOccured = false; //flag to hold if an error has occured and is used in the check for new mail ticker.  If it has, both the mail and calendar are checked until the problem is resolved.  This stops a bug that causes the events bitmap to be blank when the connection is restored.
        private bool thumbnailsCreated = false; //if bitmaps are created then this is made true. Stops a bug that prevents thumbnails being created after network disconnection
        #endregion

        /// <summary>
        /// This method is used to start the program minimised, show the settingsForm if the username/password strings are empty, start the tickers and catch the arguments sent from Program.cs
        /// </summary>
        public GoogleManager(string[] args)
        {
            InitializeComponent();

            this.WindowState = FormWindowState.Minimized; //start the browser windows with calender in minimised
            newThumbnail = new TabbedThumbnail(this.Handle, myControl.Handle);

            //createThumbnailButtons(); //create the thumbnail buttons
            checkForBlankUsernamePassword(); //check that a username and password has been entered. If blank, the settings window is shown
            updateTimerSettings(); //update the timer settings using Properties.Settings

            //start the timers
            if (Properties.Settings.Default.RefreshBrowser)
                WebRefresher.Start();

            GetNewEventsTimer.Start();
            CheckNewMailTimer.Start();

            //look for the arguments passed by the jumplist when the application is closed.  The check for new mail button is not needed - the application opens and checks anyway.  The rest of the buttons are links
            if (args.Length > 0)
            {
                if (args[0] == "OpenCalendar")
                {
                    this.WindowState = FormWindowState.Normal; //start the browser windows with calender in minimised
                }

                if (args[0] == "ShowSettings")
                {
                    applicationSettingsForm.ShowDialog();
                    updateTimerSettings(); //update the timer settings using Properties.Settings                 
                }
                if (args[0] == "CreateNewEvent")
                    newEventForm.ShowDialog();
            }
        }

        #region Create thumbnail buttons, jumplist items and icon overlays

        /// <summary>
        /// Used to create the taskbar thumnails - not all of these buttons are added
        /// </summary>
        private void createThumbnailButtons()
        {
            #region Create button objects
            ThumbnailToolBarButton acknowledgeButton = new ThumbnailToolBarButton(GoogleCalendarApp.green_tick, "Acknowledge today's events");
            acknowledgeButton.Click += delegate
            {
                Properties.Settings.Default.dateAcknowledgedEvents = DateTime.Now.ToShortDateString();
                Properties.Settings.Default.Save();
                checkForNewMailAndEvents(true, false); //check for new mail/events
            };

            ThumbnailToolBarButton OpenMailInBrowserButton = new ThumbnailToolBarButton(GoogleCalendarApp.open_inbox, "Go to inbox");
            OpenMailInBrowserButton.Click += delegate
            {
                Process openMailInBrowser = new Process() { StartInfo = new ProcessStartInfo("https://mail.google.com/mail/?tab=cm#inbox") }; //process to open the inbox in a browser
                openMailInBrowser.Start();
            };

            ThumbnailToolBarButton OpenCalendarInBrowserButton = new ThumbnailToolBarButton(GoogleCalendarApp.open_calendar, "Open calendar in browser");
            OpenCalendarInBrowserButton.Click += delegate
            {
                Process OpenCalendarInBrowser = new Process() { StartInfo = new ProcessStartInfo("https://www.google.com/calendar/") }; //process to open the calendar in a browser
                OpenCalendarInBrowser.Start();
            };

            ThumbnailToolBarButton NewEvent = new ThumbnailToolBarButton(GoogleCalendarApp.new_event, "Create new event");
            NewEvent.Click += delegate
            {
                newEventForm.ShowDialog();
            };

            ThumbnailToolBarButton ComposeMailButton = new ThumbnailToolBarButton(GoogleCalendarApp.compose_mail, "Compose mail");
            ComposeMailButton.Click += delegate
            {
                Process composeMail = new Process() { StartInfo = new ProcessStartInfo("https://mail.google.com/mail/?tab=cm#compose") }; //process to compose a new email
                composeMail.Start();
            };

            ThumbnailToolBarButton OpenContactsButton = new ThumbnailToolBarButton(GoogleCalendarApp.open_contacts, "Open address book");
            OpenContactsButton.Click += delegate
            {
                Process OpenContacts = new Process() { StartInfo = new ProcessStartInfo("https://mail.google.com/mail/?tab=cm#contacts") }; //process to open the contacts list in a browser
                OpenContacts.Start();
            };

            ThumbnailToolBarButton OpenSettingsForm = new ThumbnailToolBarButton(GoogleCalendarApp.settings2, "Change settings");
            OpenSettingsForm.Click += delegate
            {
                applicationSettingsForm.ShowDialog();
                updateTimerSettings(); //update the timer settings using Properties.Settings
                checkForNewMailAndEvents(true, true); //check for new mail/events
            };

            ThumbnailToolBarButton NextButton = new ThumbnailToolBarButton(GoogleCalendarApp.next, "Next");
            NextButton.Click += delegate
            {
                if (emailNumber < allBitmaps.Count - 1)
                {
                    emailNumber++;
                    newThumbnail.SetImage(allBitmaps[emailNumber]);
                }
            };

            ThumbnailToolBarButton PreviousButton = new ThumbnailToolBarButton(GoogleCalendarApp.previous, "Previous");
            PreviousButton.Click += delegate
            {
                if (emailNumber > 0)
                {
                    emailNumber--;
                    newThumbnail.SetImage(allBitmaps[emailNumber]);
                }
            };
            #endregion

            windowsTaskbar.ThumbnailToolBars.AddButtons(myControl.Handle, PreviousButton, acknowledgeButton, OpenMailInBrowserButton, OpenCalendarInBrowserButton, OpenSettingsForm, NextButton); //add the buttons to the thumbnail
        }

        /// <summary>
        /// Creates a bitmap for each new email, and one for the calendar events
        /// </summary>
        private List<Bitmap> createBitmaps(List<NewMail> newEmails, List<CalendarInfo> allCalendars)
        {
            allBitmaps.Clear(); //clear the old bitmaps

            if (newEmails == null || allCalendars == null)
            {
                Bitmap errorBitmap = new Bitmap(200, 109);//create bitmap image object
                Graphics errorGraphic = Graphics.FromImage(errorBitmap); //the object used to write on the bitmap
                errorGraphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //set the quality of the graphics
                errorGraphic.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; //and the rendering
                errorGraphic.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, 200, 109)); //create a white background
                errorGraphic.DrawString("Please check network connection...", new Font("Segoe UI", 12, FontStyle.Italic, GraphicsUnit.Pixel), Brushes.Gray, new PointF(0, 90)); //Write the error message
                allBitmaps.Add(errorBitmap);
                return allBitmaps;
            }

            foreach (NewMail item in newEmails)
            {
                Bitmap mailBitmap = new Bitmap(200, 109);//create bitmap image object
                Graphics mailGraphic = Graphics.FromImage(mailBitmap); //the object used to write on the bitmap

                //check to see if the title and email address is longer than the screen, if so append them with '...'
                string title;
                if (item.Title.Length > 25)
                    title = item.Title.Substring(0, 25) + "...";
                else
                    title = item.Title;

                string senderEmail;
                if (item.SenderEmail.Length > 33)
                    senderEmail = item.SenderEmail.Substring(0, 33) + "...";
                else
                    senderEmail = item.SenderEmail;

                string summary;
                if (item.Summary.Length > 73)
                    summary = item.Summary.Substring(0, 73) + "...";
                else
                    summary = item.Summary;


                //add the text to the bitmap
                mailGraphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //set the quality of the graphics
                mailGraphic.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; //and the rendering
                mailGraphic.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, 200, 109)); //create a white background
                mailGraphic.DrawString(title, new Font("Segoe UI", 12, FontStyle.Bold, GraphicsUnit.Pixel), Brushes.Black, new PointF(0, 0)); //Write the title...
                mailGraphic.DrawString(item.SenderName, new Font("Segoe UI", 12, FontStyle.Regular, GraphicsUnit.Pixel), Brushes.Black, new PointF(0, 15)); //Write the title...
                mailGraphic.DrawLine(new Pen(new SolidBrush(Color.LightGray), 1), new Point(5, 33), new Point(195, 33)); //a line...
                mailGraphic.DrawString(summary, new Font("Segoe UI", 12, FontStyle.Regular, GraphicsUnit.Pixel), Brushes.Black, new RectangleF(new PointF(0, 34), new SizeF(200, 49))); //the main body...
                mailGraphic.DrawString(senderEmail + "\n" + item.Received.ToString(), new Font("Segoe UI", 10, FontStyle.Italic, GraphicsUnit.Pixel), Brushes.DarkGray, new PointF(1, 82)); //and finally the email address and time received

                allBitmaps.Add(mailBitmap);
            }

            //add the text to the calendar bitmap
            Bitmap calendarBitmap = new Bitmap(200, 109);//create a single bitmap image object to hold all todays calendar events**need to specify size etc.
            Graphics calendarGraphic = Graphics.FromImage(calendarBitmap); //the object used to write on the bitmap
            StringFormat strFormat = new StringFormat();
            strFormat.Alignment = StringAlignment.Far;
            calendarGraphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //set the quality of the graphics
            calendarGraphic.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; //and the rendering
            calendarGraphic.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, 200, 109)); //create a white background 
            int y = 0;

            foreach (CalendarInfo calendar in allCalendars)
            {
                foreach (GenericEvent item in calendar.CalendarItems)
                {
                    if (y < 76)
                    {
                        string[] itemDetails = item.ToStringArray(false);
                        string title;
                        int numberofCharacters = itemDetails[0].ToString().Length + itemDetails[1].ToString().Length;

                        if (numberofCharacters > 32)
                        {
                            int lengthOfSubstring = 29 - itemDetails[1].ToString().Length;
                            title = itemDetails[0].ToString().Substring(0, lengthOfSubstring) + "...";
                        }
                        else
                            title = itemDetails[0].ToString();

                        calendarGraphic.DrawString(title, new Font("Segoe UI", 12, FontStyle.Bold, GraphicsUnit.Pixel), Brushes.Black, new PointF(0, y));
                        calendarGraphic.DrawString(itemDetails[1].ToString(), new Font("Segoe UI", 12, FontStyle.Italic, GraphicsUnit.Pixel), Brushes.Gray, new PointF(199, y), strFormat);
                        y += 15;
                    }
                }
            }

            if (numberOfNewEvents > 6)
                calendarGraphic.DrawString("...more events in calendar", new Font("Segoe UI", 12, FontStyle.Italic, GraphicsUnit.Pixel), Brushes.Gray, new PointF(199, 93), strFormat);

            strFormat.Alignment = StringAlignment.Center;
            strFormat.LineAlignment = StringAlignment.Center;

            if (numberOfNewEvents == 0 && newEmails.Count == 0 && Properties.Settings.Default.CheckCalendar == true)
            {
                calendarGraphic.DrawString("no new emails or events", new Font("Segoe UI", 12, FontStyle.Italic, GraphicsUnit.Pixel), Brushes.Gray, new RectangleF(new PointF(0, 0), new SizeF(new PointF(199, 93))), strFormat);
            }

            if (numberOfNewEvents == 0 && newEmails.Count != 0 && Properties.Settings.Default.CheckCalendar == true)
            {
                calendarGraphic.DrawString("no events today", new Font("Segoe UI", 12, FontStyle.Italic, GraphicsUnit.Pixel), Brushes.Gray, new RectangleF(new PointF(0, 0), new SizeF(new PointF(199, 93))), strFormat);
            }

            if (newEmails.Count == 0 && Properties.Settings.Default.CheckCalendar == false)
            {
                calendarGraphic.DrawString("no new emails", new Font("Segoe UI", 12, FontStyle.Italic, GraphicsUnit.Pixel), Brushes.Gray, new RectangleF(new PointF(0, 0), new SizeF(new PointF(199, 93))), strFormat);
            }

            allBitmaps.Add(calendarBitmap);
            return allBitmaps;
        }

        /// <summary>
        /// Sets the Thumbnail image in the taskbar.  This number is moved forward/backward by increasing/decreasing the emailNumber variable.
        /// </summary>
        private void createThumbnail(List<Bitmap> allBitmaps)
        {
            if (windowsTaskbar.TabbedThumbnail.IsThumbnailPreviewAdded(newThumbnail)) //first, if there already a thumbnail then remove it
                windowsTaskbar.TabbedThumbnail.RemoveThumbnailPreview(newThumbnail);

            newThumbnail.Title = "New mail/today's events:"; //set the title of the thumbnail
            newThumbnail.SetWindowIcon(GoogleCalendarApp.new_mail_letter); //make the icon a new email icon

            newThumbnail.TabbedThumbnailActivated += new EventHandler<TabbedThumbnailEventArgs>(showWindow); //create the delegate to show the main window when the thumbnail is clicked
            newThumbnail.TabbedThumbnailClosed += new EventHandler<TabbedThumbnailClosedEventArgs>(closeApplication); //create the delegate to close the application when the cross is clicked in the thumbnail

            windowsTaskbar.TabbedThumbnail.AddThumbnailPreview(newThumbnail); //add the thumbnail to the taskbar
            newThumbnail.SetImage(allBitmaps[emailNumber]); //change the image to the current bitmap

            createThumbnailButtons(); //create the thumbnail buttons
            thumbnailsCreated = true;
        }

        //delegate to show the main window when the thumbnail is clicked
        private void showWindow(object sender, TabbedThumbnailEventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
        }

        //delegate to close the application when the cross is clicked in the thumbnail
        private void closeApplication(object sender, TabbedThumbnailEventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Adds new emails and events to of the jumplist.
        /// </summary>
        /// <param name="newEmails"></param>
        private void AddItemsToJumpList(List<NewMail> newEmails, List<CalendarInfo> allCalendars)
        {
            if (newEmails == null || allCalendars == null)
                return;

            myJumpList = Microsoft.WindowsAPICodePack.Taskbar.JumpList.CreateJumpList(); //create/clear the jumplist

            #region Create jumplist task items
            //add the jumplist items for application functions
            myJumpList.AddUserTasks(new JumpListLink("https://mail.google.com/mail/?shva=1#compose", "Compose new mail")
            {
                IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 214)
            });

            myJumpList.AddUserTasks(new JumpListLink(Assembly.GetEntryAssembly().Location, "Create new event")
            {
                IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 76),
                Arguments = "CreateNewEvent"
            });

            myJumpList.AddUserTasks(new JumpListLink("https://mail.google.com/mail/?tab=cm#inbox", "Go to inbox")
            {
                IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 299)
            });

            myJumpList.AddUserTasks(new JumpListLink(Assembly.GetEntryAssembly().Location, "Got to calendar")
            {
                IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 251),
                Arguments = "OpenCalendar"
            });

            myJumpList.AddUserTasks(new JumpListLink("https://mail.google.com/mail/?tab=cm#contacts", "Go to contacts")
            {
                IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 264)
            });

            myJumpList.AddUserTasks(new JumpListLink(Assembly.GetEntryAssembly().Location, "Check for new mail")
            {
                IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 238),
                Arguments = "CheckForNewMail"
            });

            myJumpList.AddUserTasks(new JumpListLink(Assembly.GetEntryAssembly().Location, "Settings")
            {
                IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 207),
                Arguments = "ShowSettings"
            });
            #endregion

            //add the jumplist items for new emails
            JumpListCustomCategory newEmailCat = new JumpListCustomCategory("New emails"); //create the custom category 'New emails'
            foreach (NewMail item in newEmails) //for each mail item create a new jump list link
            {
                JumpListLink newMail = new JumpListLink(item.Link, item.Title);
                newMail.IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 156);
                newEmailCat.AddJumpListItems(newMail); //add to the custom category
            }

            //add the jumplists items for todays events
            foreach (CalendarInfo eventsInCalendar in allCalendars)
            {
                JumpListCustomCategory todaysEventsCat = new JumpListCustomCategory("Today's events: " + eventsInCalendar.Title); //create the custom category with the name of the calendar
                JumpListLink newEvent;
                foreach (GenericEvent item in eventsInCalendar.CalendarItems) //for each calendar item create a new jump list link
                {
                    string[] itemDetails = item.ToStringArray(true);
                    newEvent = new JumpListLink(item.Link, itemDetails[0] + itemDetails[1]);
                    newEvent.IconReference = new IconReference(@"%SystemRoot%\system32\SHELL32.dll", 253); //load the icon
                    todaysEventsCat.AddJumpListItems(newEvent); //add to the custom category
                }
                myJumpList.AddCustomCategories(todaysEventsCat); //when done add the custome category to the jumplist
            }
            myJumpList.AddCustomCategories(newEmailCat); //when done add the custome category to the jumplist
            myJumpList.Refresh(); //refresh the jumplist
        }

        /// <summary>
        /// Sets the taskbar icon overlay depending on how many unread emails there are and if there are events today that have not been acknowledged.
        /// The icon for unread emails superseeds the icon for unacknowledged events.  If there are more than 9 unread emails, a plus sign is shown instead.
        /// </summary>
        /// <param name="numberOfEmails">Number of unread emails</param>
        private void setOverlayIcons(int numberOfEmails, int numberOfEvents)
        {
            if (numberOfEmails == -1 || numberOfEvents == -1)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Exclamation_mark_icon, "Connection Error");
            if (numberOfEmails == 0 && numberOfEvents == 0)
                windowsTaskbar.SetOverlayIcon(this.Handle, null, null);
            if (numberOfEmails == 0 && numberOfEvents > 0 && Properties.Settings.Default.dateAcknowledgedEvents == DateTime.Now.ToShortDateString())
                windowsTaskbar.SetOverlayIcon(this.Handle, null, null);
            if (numberOfEmails == 0 && numberOfEvents > 0 && Properties.Settings.Default.dateAcknowledgedEvents != DateTime.Now.ToShortDateString())
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.green_cross, "Events today");
            if (numberOfEmails == 1)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_1_icon, "1 new email");
            if (numberOfEmails == 2)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_2_icon, "2 new emails");
            if (numberOfEmails == 3)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_3_icon, "3 new emails");
            if (numberOfEmails == 4)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_4_icon, "4 new emails");
            if (numberOfEmails == 5)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_5_icon, "5 new emails");
            if (numberOfEmails == 6)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_6_icon, "6 new emails");
            if (numberOfEmails == 7)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_7_icon, "7 new emails");
            if (numberOfEmails == 8)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_8_icon, "8 new emails");
            if (numberOfEmails == 9)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Number_9_icon, "9 new emails");
            if (numberOfEmails > 9)
                windowsTaskbar.SetOverlayIcon(GoogleCalendarApp.Math_plus_icon, newEmails.Count.ToString() + " new emails");
        }

        #endregion

        #region Check for new events/emails


        /// <summary>
        /// Checks for new mail. Calls GoogleMailChecker.CheckForNewMail and passes the username/password in Properties.Settings.
        /// Plays a chime if there is new mail.  After the chime is played, it puts the number of new messages in the property numberOfNewEmails.
        /// The next time this method is called (ie after the next interval) if the number of new email messages is the same as last time the chime is not played
        /// This means that the chime will not play over and over again.
        /// </summary>
        private void checkForNewMailAndEvents(bool checkForNewMail, bool checkForNewEvents)
        {
            int numberOfNewEmails = 0; //holds the number of new emails
            errorOccured = false; //flag to hold if an error has occured and is used in the check for new mail ticker.  If it has, both the mail and calendar are checked until the problem is resolved.  This stops a bug that causes the events bitmap to be blank when the connection is restored.

            if (checkForNewMail == true) //check for new emails
            {
                try
                {
                    SecureString password = (EncryptionClass.DecryptString(Properties.Settings.Default.password)); //the googlemail password
                    newEmails = GoogleMailChecker.CheckForNewMail(EncryptionClass.ToInsecureString(EncryptionClass.DecryptString(Properties.Settings.Default.username)), password); //get the new mail and place it in a list
                    numberOfNewEmails = newEmails.Count; //return the number of new emails, to be used when placing the icon overlay                
                }
                catch (Exception)
                {
                    numberOfNewEmails = -1;
                    errorOccured = true;
                }
            }

            if (checkForNewEvents == true && Properties.Settings.Default.CheckCalendar == true) //if the last attempt caused an error, or if it is requested check for new events
            {
                numberOfNewEvents = 0; //hold the number of new events
                try
                {
                    AllCalendars = GoogleCalendarChecker.CheckForCalendarEvents(EncryptionClass.ToInsecureString(EncryptionClass.DecryptString(Properties.Settings.Default.username)), EncryptionClass.ToInsecureString(EncryptionClass.DecryptString(Properties.Settings.Default.password)));
                    foreach (CalendarInfo item in AllCalendars)
                    {
                        numberOfNewEvents += item.CalendarItems.Count; //count the number of new events
                    }
                }
                catch (Exception)
                {
                    numberOfNewEvents = -1;
                    errorOccured = true;
                }
            }

            if (GoogleMailChecker.checkIfNewBitmapRequired(newEmails, oldEmailsForBitmaps, thumbnailsCreated) || GoogleCalendarChecker.checkIfNewBitmapRequired(AllCalendars, oldAllCalendarsForBitmaps, thumbnailsCreated)) //checks to see if there has been any changes to the emails. If there are, new bitmaps and buttons are created
            {
                //MessageBox.Show("newEmails: " + newEmails.Count + "\n" + "oldEmailsForBitmaps: " + oldEmailsForBitmaps.Count);
                emailNumber = 0; //set this variable back to 0 so you view the latest email first in the thumbnail, and stop an error (the integar being bigger than the size of the list if you mark mail as read)
                createThumbnail(createBitmaps(newEmails, AllCalendars)); //create the thumbnails
                oldEmailsForBitmaps = newEmails;
                oldAllCalendarsForBitmaps = AllCalendars;

            }

            AddItemsToJumpList(newEmails, AllCalendars); //populate the jumplist with emails and events

            //finally, notify the user there is new mail
            setOverlayIcons(numberOfNewEmails, numberOfNewEvents);
            if (GoogleMailChecker.checkForNewMailSinceLastCheck(newEmails, oldEmails)) //check to see if the list of emails retrieved from google is different from the last list received.
            {
                if (Properties.Settings.Default.NewMailPlaySound)
                    newMailSound.Play(); //... if it is then play a sound unless sound is turned off
                oldEmails = newEmails; //...and make this new list the old list for the next check
            }
        }

        #endregion

        #region Application Timers

        /// <summary>
        /// Event to refresh the GoogleCalendarWebBrowser
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WebRefresher_Tick(object sender, EventArgs e)
        {
            GoogleCalendarWebBrowser.Refresh(); //refresh the calendar web page 
        }

        /// <summary>
        /// Timer event to check new mail
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckNewMailTimer_Tick(object sender, EventArgs e)
        {
            if (!errorOccured)
                checkForNewMailAndEvents(true, false); //check for new mail/events
            else
            {
                checkForNewMailAndEvents(true, true); //check for new mail/events
            }
        }

        /// <summary>
        /// Timer event to check calendar
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GetNewEventsTimer_Tick(object sender, EventArgs e)
        {
            checkForNewMailAndEvents(true, true); //check for new mail/events
        }

        #endregion

        #region Misc. application methods/events

        /// <summary>
        /// Checks Properties.Settings for entries in username and password. If blank, then the settings form is shown. The settings button also sets the refresh interval.
        /// </summary>
        private void checkForBlankUsernamePassword()
        {
            if (Properties.Settings.Default.username == "" || Properties.Settings.Default.password == "")
            {
                applicationSettingsForm.ShowDialog();
                updateTimerSettings(); //update the timer settings using Properties.Settings
            }
        }

        /// <summary>
        /// Called after the GoogleCalendar form has finished loading and sets the icon overlay if there is unseen events.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GoogleCalendar_Shown(object sender, EventArgs e)
        {
            checkForNewMailAndEvents(true, true); //check for new mail/events
        }

        /// <summary>
        /// Updates the timer settings using Properties.Settings
        /// </summary>
        private void updateTimerSettings()
        {
            WebRefresher.Interval = Properties.Settings.Default.CalendarRefreshRate * 1000; //set the timer interval for the calendar web browser
            GetNewEventsTimer.Interval = Properties.Settings.Default.GetNewEventsTime * 60000; //set the timer interval for getting new events, in minutes
            CheckNewMailTimer.Interval = Properties.Settings.Default.CheckNewMailTime * 1000; //set the timer internal for checking for new mail
            if (!Properties.Settings.Default.RefreshBrowser)
                WebRefresher.Stop();
            else
                WebRefresher.Start();
        }

        /// <summary>
        /// Used to receive messages for other instances of this application.  Vital to have the jumplist buttons that open up settings, check for new mail, open the browser window and crete new events to work
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == NativeMethods.SHOW_SETTINGS)
            {
                applicationSettingsForm.ShowDialog();
                updateTimerSettings(); //update the timer settings using Properties.Settings

                //check for new mail and events to update settings
                checkForNewMailAndEvents(true, true); //check for new mail/events
            }
            if (m.Msg == NativeMethods.CHECK_NEW_MAIL)
            {
                //depending on the setting, either check for new mail or new mail and new events
                if (Properties.Settings.Default.CheckForNewMailAndEvents)
                    checkForNewMailAndEvents(true, true); //check for new mail/events
                else
                    checkForNewMailAndEvents(true, false); //check for new mail/events  A new list of events is not downloaded - the previous list is used instead.
            }
            if (m.Msg == NativeMethods.NEW_EVENT)
            {
                newEventForm.ShowDialog();
            }
            if (m.Msg == NativeMethods.OPEN_CALENDAR)
            {
                if (WindowState == FormWindowState.Minimized)
                {
                    WindowState = FormWindowState.Normal;
                }
                // get our current "TopMost" value (ours will always be false though)
                bool top = TopMost;
                // make our form jump to the top of everything
                TopMost = true;
                // set it back to whatever it was
                TopMost = top;
            }
            base.WndProc(ref m);
        }
        #endregion
    }
}
